#include "stdafx.h"
#ifdef LIT_OGRE_SUPPORT
#include "LitMovable.h"
#include <OgreSceneNode.h>
#include <OgreMovableObject.h>

namespace Lit
{
	Movable::Movable(MovableType type, const String &name)
		: mType( type )
		, mName( name )
		, mCreated( false )
		, mObject( NULL )
		, mDatas( name )
	{
	}
	Movable::Movable( const Movable& rk )
		: mDatas(rk.mDatas)
	{
		mMgr = rk.mMgr;
		mName = rk.mName;
		mNode = rk.mNode;
		mCreated = rk.mCreated;
		mType = rk.mType;
		mObject = rk.mObject;
		mListeners = rk.mListeners;
	}
	Movable::~Movable( ){ }

	std::vector<MovableListener*>& Movable::getListeners(){ return mListeners; }
	const std::vector<MovableListener*>& Movable::getListeners() const{ return mListeners; }
	
	MovableDatas& Movable::getDatas(){ return mDatas; }
	const MovableDatas& Movable::getDatas() const{ return mDatas; }
	bool Movable::hasData( const String &name ) const{ return mDatas.hasData( name ); }
	
	void Movable::addListener( MovableListener * l ){ if( l ) mListeners.push_back(l); }
	bool Movable::hasListener( MovableListener * l ){ for( auto i=mListeners.begin(); i!=mListeners.end(); i++ ) if( *i == l ) return true; return false; }
	void Movable::removeListener( MovableListener * l ){ for( auto i=mListeners.begin(); i!=mListeners.end(); i++ ) if( *i == l ){ mListeners.erase( i ); return; } }

	void Movable::_setMovable( Ogre::MovableObject * obj ){ mObject = obj; }
	Ogre::MovableObject* Movable::getMovable(){ return mObject; }
	const Ogre::MovableObject* Movable::getMovable() const{ return mObject ; }

	Ogre::Vector3			Movable::getSize() const{return getBoundingBox().getSize(); }
	Ogre::AxisAlignedBox	Movable::getBoundingBox() const{ if( mNode && mNode->getAttachedObject(0) ) return mNode->getAttachedObject(0)->getBoundingBox(); return Ogre::AxisAlignedBox::BOX_NULL; }

	String Movable::getMovableTypeStr() const{ return trMovableType(mType); }
	MovableType Movable::getMovableType() const{ return mType; }

	void Movable::setMovableType( MovableType t ){ mType = t; }

	void Movable::setPosition( const Ogre::Vector3 &pos ){ 
		if( !mCreated ) return;  
		Vec3 old = mNode->getPosition();
		for( auto i=mListeners.begin(); i!=mListeners.end(); i++ )
			if( (*i) && ((*i)->mask()&mType)!=0 ) if( !(*i)->moveObject( this, pos ) ) return;
		mNode->setPosition( pos ); 
	}
	void Movable::setOrientation( const Ogre::Quaternion &q )
	{ 
		if( !mCreated ) return; 
		Quat old(mNode->getOrientation());
		for( auto i=mListeners.begin(); i!=mListeners.end(); i++ )
			if( (*i) && ((*i)->mask()&mType)!=0 ) if( !(*i)->orientObject( this, q ) ) return;
		mNode->setOrientation( q ); 
	}
	void Movable::setScale( const Ogre::Vector3 &s ){ 
		if( !mCreated ) return; 
		Vec3 old = mNode->getScale();
		for( auto i=mListeners.begin(); i!=mListeners.end(); i++ )
			if( (*i) && ((*i)->mask()&mType)!=0 ) if( !(*i)->scaleObject( this, s ) ) return;
		mNode->setScale( s );
	}
	Ogre::Vector3 Movable::getPosition( ) const{ if( !mCreated ) return Ogre::Vector3::ZERO; return mNode->getPosition(); }
	Ogre::Quaternion Movable::getOrientation( )const{ if( !mCreated ) return Ogre::Quaternion::IDENTITY; return mNode->getOrientation( ); }
	Ogre::Vector3 Movable::getScale( )const{ if( !mCreated ) return Ogre::Vector3::ZERO; return mNode->getScale( ); }
		
	String Movable::getName() const{ return mName; }
	
	const OgreSceneNodePtr Movable::getNode() const{ return mNode; }

	void Movable::setCreated( bool c ){ mCreated = c; }
	bool Movable::isCreated() const{ return mCreated; }
};

#endif